/*
 * @Date: 2022-03-02 20:17:15
 * @LastEditors: zhaoxm
 * @LastEditTime: 2022-09-15 17:04:22
 * @Description: 数据处理，方便区分多种处理方式
 */

import { downLoadBlob, filedToObject, removeEmptyParams as removeEmptyParameters, setOptionsFiled } from "./utils"
import { APP_CACHE_API_LIST } from "@/utils/storage/constant"
import { showMessage, showMessageBox } from "@/utils/message"
import { getAxiosCanceler } from "./axiosCancel"
import { checkStatus } from "./checkStatus"
import { getToken, isError, logout } from "@/utils/auth"
import { ResultEnum } from "./enum"
import cache from "@/utils/storage"
import _ from "lodash"

const axiosCanceler = getAxiosCanceler()

const exceptionHandle = async (result, { ifShowErrorModal, errorMessageMode }) => {
  if (isError(result.data.errorCode)) throw result.data 

  result.data.errorCode = String(result.data.errorCode)

  // 返回异常业务code
  if (!result.data[ResultEnum.TYPE] || result.data.errorCode !== ResultEnum.SUCCESS) {
    // 如果业务code异常，用户选择不展示全局的error弹框
    if (ifShowErrorModal) {
      if (errorMessageMode === "message") {
        showMessage(result.data.message, "error")
      } else {
        showMessageBox("提示", result.data.message)
      }
    }
    
    throw result.data
  }
}

export const transform = {
  // 请求之前处理用户传入的 params
  beforeRequestHook: (config, options) => {
    if (options.isCache) options.cacheTime = options.defCacheTime

    // 如果用户设置了 不传为空值的参数给后端 ， 需要在这过滤一下
    if (options.isRemoveEmptyParams) {
      config.data = removeEmptyParameters(config.data)
    }

    if (_.isObject(config.data) && config.data.start) {
      config.data.withTotal = true
      config.data.withDeleted = true
      config.data.withDisabled = true
    }
    return config
  },

  // 请求拦截器,请求之前处理config
  requestInterceptors: (config, requestOptions) => {
    // const ignoreCancel = config.requestOptions.ignoreCancelToken
    const ignoreCancel = false
    ignoreCancel && axiosCanceler.addPending(config)

    const token = getToken()
    // 接口是否需要使用TOKEN
    if (requestOptions.withToken) {
      if (!token) logout()
      config.headers["Authorization"] = token
    }

    if (requestOptions.responseType) {
      config.responseType = requestOptions.responseType
    }

    return config
  },

  // 响应数据之前做哪些处理
  beforeResHook(config, send) {
    const { requestOptions, url, params, data } = config

    const appCacheList = cache.get(APP_CACHE_API_LIST)

    if (
      appCacheList &&
      appCacheList.includes(url) &&
      cache.get(`${APP_CACHE_API_LIST}_${url}`)
    ) {
      return cache.get(`${APP_CACHE_API_LIST}_${url}`)
    }

    // 判断是否有缓存数据，如果有直接返回即可
    const cacheData = cache.get(url)
    const parameters = params || data

    if (
      requestOptions.cacheTime &&
      cacheData &&
      _.isEqual(cacheData.params, parameters)
    ) {
      return cacheData.data
    }

    return send()
  },

  // 响应拦截器处理
  // eslint-disable-next-line unicorn/prevent-abbreviations
  responseInterceptors: async (res, requestOptions) => {
    const {
      responseType,
      isAutoDownload,
      cacheTime,
      field,
      isReturnNativeResponse,
    } = requestOptions
    const result = res.data.data || []

    res && axiosCanceler.removePending(res.config)

    // 下载文件
    if (responseType === "blob") {
      if (res.data.type === "application/json") {
        const reader = new FileReader()
        reader.readAsText(res.data, "utf8")
        return new Promise((resolve, reject) => {
          reader.addEventListener("load", async () => {
            const readerres = JSON.parse(reader.result)
            res.data = readerres
            try {
              const codeHandle = await exceptionHandle(res, requestOptions)
              if (codeHandle) return codeHandle()
              resolve(readerres.data)
            } catch (error) {
              reject(error)
            }
          })
        })
      }

      if (res.config?.data?.constructor === FormData) {
        let isAutoDownload = res.config.data.get("isAutoDownload")
        // 这里拿到的 formDate key 是一个字符串 ，所以需要转换一下
        isAutoDownload = isAutoDownload !== "false"
        if (isAutoDownload !== null) return downLoadBlob(res, isAutoDownload)
      }

      return downLoadBlob(res, isAutoDownload)
    }

    const codeHandle = await exceptionHandle(res, requestOptions)
    if (codeHandle) return codeHandle()

    // 如果用户设置了 缓存字段 , 返回原生响应体暂时 不做缓存处理
    if (cacheTime && _.isNumber(cacheTime) && !isReturnNativeResponse) {
      const { url, data, params } = res.config
      const cacheData = {
        data: result,
        params: data
          ? JSON.parse(data)
          : params,
      }

      cache.save(url, cacheData, cacheTime)
    }

    // 设置字段映射
    if (field) {
      const fieldObject = filedToObject(field)
      if (res.data.data.records) {
        setOptionsFiled(res.data.data.records, fieldObject)
      } else {
        setOptionsFiled(result, fieldObject)
      }
    }

    // 是否需要原生响应头
    if (isReturnNativeResponse) return res.data

    const appCacheList = cache.get(APP_CACHE_API_LIST)
    if (appCacheList && appCacheList.includes(res.config.url)) {
      cache.save(`${APP_CACHE_API_LIST}_${res.config.url}`, result)
    }

    return result
  },

  // 响应错误处理
  responseInterceptorsCatch: (error) => {
    checkStatus(error)
    return Promise.reject(error)
  },
}
